package com.boarsoft.rpc.sidecar;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import com.boarsoft.rpc.core.DynamicInvoker;
import com.boarsoft.rpc.core.RpcContext;

public class RpcSidecarInvoker implements DynamicInvoker {
	private static final Logger log = LoggerFactory.getLogger(RpcSidecarInvoker.class);

	protected RpcContext rpcContext;

	protected Object reference;
	protected Map<Integer, Method> methodMap = new ConcurrentHashMap<>();

	public RpcSidecarInvoker(String rid, RpcContext rpcContext) {
		this.rpcContext = rpcContext;
		this.reference = rpcContext.getBean(rid);
		log.debug("new RpcSidecarInvoker for refrence {}", rid);
	}

	@Override
	public Object invoke(int methodId, Object[] args) throws Throwable {
		Method m = methodMap.get(methodId);
		if (m == null) {
			synchronized (methodMap) {
				// 根据本地服务（代理）方法，查找实际需要调用的远程引用方法
				m = methodMap.get(methodId);
				if (m == null) {
					m = rpcContext.getMyMethod(methodId);
					m = reference.getClass().getMethod(m.getName(), m.getParameterTypes());
					methodMap.put(methodId, m);
				}
			}
		}
		// 反射调用 reference method 发起RPC调用
		return m.invoke(reference, args);
	}

	@Override
	public void setApplicationContext(ApplicationContext ctx) {
		// Nothing to do
	}

}
